package com.quanyan.club.service.impl;

import com.github.ltsopensource.core.json.JSON;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.ApiResponseEnum;
import com.quanyan.club.entity.db.*;
import com.quanyan.club.entity.vo.req.movement.ReqClubListInfo;
import com.quanyan.club.entity.vo.resp.movement.ClubIntegralInfo;
import com.quanyan.club.entity.vo.resp.movement.RespClubIntegralRank;
import com.quanyan.club.mapper.*;
import com.quanyan.club.service.ClubIntegralService;
import com.quanyan.club.service.ClubSearchBizService;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.Limit;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xian-guo
 * @email 498152332@qq.com
 * @date 2016/12/13.
 */
@Service("clubIntegralService")
public class ClubIntegralServiceImpl implements ClubIntegralService{

    private static Logger logger = Logger.getLogger(ClubIntegralServiceImpl.class);

    @Autowired
    private TbClubMapper tbClubMapper;

    @Autowired
    private TbClubIntegralRuleMapper tbClubIntegralRuleMapper;

    @Autowired
    private ClubIntegralMapper clubIntegralMapper;

    @Autowired
    private ClubSearchBizService clubSearchBizService;//添加索引

    /**
     * 活动评论后，计算俱乐部积分
     * @param clubId
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public boolean modifyClubCommentStar(int clubId,double star) {
        long startTime=System.currentTimeMillis();
        Map<String,Object> param=this.getPointBy(1);//积分规则
        List<Double> gradeList= (List<Double>) param.get("grade");//评分
        List<Double> pointList= (List<Double>) param.get("point");//对应积分
        Double rate= (Double) param.get("rate");//权重
        double pointStart = 0.0;
        double pointEnd = 0.0;
        double newStar=0.00;
        synchronized (this) {
            DecimalFormat df=new DecimalFormat("#.00");
            df.setRoundingMode(RoundingMode.HALF_UP);
            TbClub tbClub=tbClubMapper.selectByPrimaryKey(clubId);
            if(null !=tbClub){
                double oldStar=tbClub.getStar();//总星数
                if (tbClub.getActivityCount()==0){//新俱乐部第一次评论，特殊处理
                    newStar=Double.valueOf(df.format(star));
                }else{
                    newStar=(oldStar+star)/(tbClub.getActivityCount()+1);
                    oldStar=Double.valueOf(df.format(oldStar/tbClub.getActivityCount()));
                }
                newStar=Double.valueOf(df.format(newStar));
                logger.warn("俱乐部id"+clubId+"-传来的分-//"+star+"-------活动评价后--俱乐部---老积分-//"+oldStar+"---新积分----//"+newStar);
                for (int i = 0; i < gradeList.size(); i++) {
                    if (oldStar>=gradeList.get(gradeList.size()-1)){
                        pointStart=pointList.get(pointList.size()-1);
                        break;
                    }
                    if (oldStar<=gradeList.get(i)){
                        pointStart=pointList.get(i);
                        break;
                    }
                }
                for (int i = 0; i < gradeList.size(); i++) {
                    if (newStar>=gradeList.get(gradeList.size()-1)){
                        pointEnd=pointList.get(pointList.size()-1);
                        break;
                    }
                    if (newStar<=gradeList.get(i)){
                        pointEnd=pointList.get(i);
                        break;
                    }
                }
                logger.warn(rate+"---"+"-pointEnd--//"+pointEnd+"--pointStart-//"+pointStart+"-------"+Math.round((1+rate) * pointEnd * 10)+"-++++++++++-//"+Math.round((1+rate) * pointStart * 10));
                long clubIntegra=Math.round((1+rate) * pointEnd * 10)-Math.round((1+rate) * pointStart * 10);//积分的增量(权重 * 评论后的积分差值) * 10
                //更新该俱乐部星级
                return this.updateClubIntegral(clubId,clubIntegra,startTime,Double.valueOf(df.format(tbClub.getStar()+star)),true);
            }
        }
        clubSearchBizService.updateClubStarToIndex(clubId,newStar);//跟新俱乐部星级索引
        return false;
    }

    /**
     * 计算加入俱乐部统计积分
     * type :加入0,退出：1
     * @param clubId
     */
    @Override
    public boolean joinClubCountSum(int clubId,int type) {
        logger.warn("type------>>>>>"+type);
        long startTime=System.currentTimeMillis();
        Map<String,Object> param=this.getPointBy(2);//积分规则
        List<Double> gradeList= (List<Double>) param.get("grade");//人数
        List<Double> pointList= (List<Double>) param.get("point");//对应积分
        Double rate= (Double) param.get("rate");//权重
        synchronized (this) {
            Map<String,Object> paramMap=new HashMap<>();
            paramMap.put("clubId",clubId);
            List<ClubIntegralInfo> clubIntegralInfoList= clubIntegralMapper.getClubMember(paramMap);
            if (!CollectionUtils.isEmpty(clubIntegralInfoList)){
                ClubIntegralInfo clubIntegralInfo= clubIntegralInfoList.get(0);
                int memberStart=0;//加入或退出前人数
                if (type==0){//加入俱乐部
                    memberStart=clubIntegralInfo.getMemberNum()-1;
                }else if(type==1){//退出俱乐部
                    memberStart=clubIntegralInfo.getMemberNum()+1;
                }else{
                    throw new BizException("type字段不正确");
                }
                int memberEnd=clubIntegralInfo.getMemberNum();//当前人数
                double pointStart=0.00;//加入前
                double pointEnd=0.00;//加入后
                logger.warn("俱乐部id"+clubId+"---俱乐部--当前人数--//"+memberStart+"-type--0加入，1退出//"+type+"-加入or退出后人数--//"+memberEnd);
                for (int i = 0; i < gradeList.size(); i++) {
                    if(memberStart>gradeList.get(gradeList.size()-1)){
                        pointStart=pointList.get(pointList.size()-1);
                        break;
                    }
                    if (memberStart<gradeList.get(0)){//<1  =0分
                        pointStart=pointList.get(0);
                        break;
                    }
                    if (memberStart==gradeList.get(0)){//=1 =0.5分
                        pointStart=pointList.get(1);
                        break;
                    }
                    if (memberStart<=gradeList.get(i)){
                        pointStart=pointList.get(i);
                        break;
                    }
                }
                for (int i = 0; i < gradeList.size(); i++) {
                    if(memberEnd>gradeList.get(gradeList.size()-1)){
                        pointEnd=pointList.get(pointList.size()-1);
                        break;
                    }
                    if (memberEnd<gradeList.get(0)){//<1  =0分
                        pointEnd=pointList.get(0);
                        break;
                    }
                    if (memberEnd==gradeList.get(0)){//=1 =0.5分
                        pointEnd=pointList.get(1);
                        break;
                    }
                    if (memberEnd<=gradeList.get(i)){
                        pointEnd=pointList.get(i);
                        break;
                    }
                }
                logger.warn(rate+"---"+"pointEnd--//"+pointEnd+"--pointStart--//"+pointStart+"-------//"+Math.round((1+rate) * pointEnd * 10)+"-++++++++++-//"+Math.round((1+rate) * pointStart * 10));
                long clubIntegra=Math.round((1+rate) * pointEnd * 10)-Math.round((1+rate) * pointStart * 10);//积分的增量(权重 * 评论后的积分差值) * 10
                //跟新俱乐部星级
                return this.updateClubIntegral(clubId,clubIntegra,startTime,0.0,false);
            }
        }
        return false;
    }

    /**
     * 周任务算积分
     * @param clubId
     * @param completeNum  周任务实际人数
     * @param taskNum    周任务任务人数
     * @param completeMem  周任务实际活动数
     * @param taskMem  周任务任务活动数
     * @return
     */
    @Override
    public boolean modifyClubWeekTaskStar(int clubId, int completeNum,int taskNum, int completeMem,int taskMem) {
        logger.warn("----------completeNum--:"+completeNum+"--taskNum--:"+taskNum+"--completeMem--;"+completeMem+"--taskMem--:"+taskMem);
        long startTime=System.currentTimeMillis();
        Map<String,Object> param=this.getPointBy(3);
        List<Double> gradeList= (List<Double>) param.get("grade");//周任务
        List<Double> pointList= (List<Double>) param.get("point");//对应积分
        Double rate= (Double) param.get("rate");//权重
        DecimalFormat df=new DecimalFormat("#.0");
        df.setRoundingMode(RoundingMode.HALF_UP);
        double actualInte=Double.valueOf(df.format((completeNum/Double.valueOf(taskNum)+completeMem/Double.valueOf(taskMem))/2.0f));
        if (completeNum<taskNum && completeMem>=taskMem){//只完成某一个周任务
            actualInte=Double.valueOf(df.format((completeNum/Double.valueOf(taskNum)+1.0)/2.0f));
        }
        if (completeNum>=taskNum && completeMem<taskMem){//只完成某一个周任务
            actualInte=Double.valueOf(df.format((1.0+completeMem/Double.valueOf(taskMem))/2.0f));
        }
        //double actualInte=2.1;
        logger.warn("俱乐部id"+clubId+"------周任务完成系数---------//"+actualInte);
        double diffInte=0.00f;
        for (int i=0;i<gradeList.size();i++){
            if (actualInte>=gradeList.get(gradeList.size()-1)){//>=2
                diffInte=pointList.get(pointList.size()-1);
                break;
            }
            if(actualInte==gradeList.get(5)){//=1
                diffInte=pointList.get(6);
                break;
            }
            if (actualInte<gradeList.get(0)){//<0.1
                break;
            }
            if (actualInte==gradeList.get(0)){//=0.1
                diffInte=pointList.get(i+1);
                break;
            }
            if (actualInte<=gradeList.get(i)){//其他情况
                diffInte=pointList.get(i);
                if (actualInte>1){//>1,取后一位
                    diffInte=pointList.get(i+1);
                }
                break;
            }

        }
        logger.warn(rate+"---"+"diffInte--//"+diffInte);
        long clubIntegra=Math.round((1+rate) * diffInte * 10);//积分的增量(权重 * 评论后的积分差值) * 10
        logger.warn("------周任务积分数量---------//"+clubIntegra);
        return this.updateClubIntegral(clubId,clubIntegra,startTime,0.0,false);
    }

    /**
     * 计算周任务参与人数
     * @param clubId
     * @param memberNum
     */
    @Override
    public void calcClubActivityMember(int clubId, int memberNum) {
        logger.warn("----------clubId:"+clubId+"----memberNum--:"+memberNum);
        long startTime=System.currentTimeMillis();
        Map<String,Object> param=this.getPointBy(8);
        List<Double> gradeList= (List<Double>) param.get("grade");//周任务
        List<Double> pointList= (List<Double>) param.get("point");//对应积分
        Double rate= (Double) param.get("rate");//权重
        double diffInte=0.00f;
        for(int i=0;i<gradeList.size();i++){
            if(memberNum>gradeList.get(gradeList.size()-1)){
                diffInte=pointList.get(pointList.size()-1);
                break;
            }
            if (memberNum<=gradeList.get(i)){
                diffInte=pointList.get(i);
                break;
            }
        }
        long clubIntegra=Math.round((1+rate) * diffInte * 10);//积分的增量(权重 * 评论后的积分差值) * 10
        logger.warn("------周任务参与人数积分数量---------//"+clubIntegra);
        this.updateClubIntegral(clubId,clubIntegra,startTime,0.0,false);
    }


    /**
     * 跟新俱乐部星级
     * @param clubId
     * @param clubIntegra  积分增量
     */
    private boolean updateClubIntegral(int clubId,long clubIntegra,long startTime,double star,boolean isInsert){
        logger.warn("----积分差值-------//"+clubIntegra);
        Map<String, Object> inteMap = new HashMap<>();
        inteMap.put("clubId", clubId);
        if (star!=0.0){
            inteMap.put("star",star);
        }
        if (isInsert){//是否增加评论数
            inteMap.put("isInsert","insert");
        }
        inteMap.put("integral", clubIntegra);
        int upCount = clubIntegralMapper.updateTbClubIntegral(inteMap);//跟新到俱乐部积分中
        if (upCount > 0) {
            long endTime=System.currentTimeMillis();
            logger.warn("---------俱乐部跟新积分成功----time-consume----------------------//"+(endTime-startTime));
            return true;
        }
        return false;
    }

    private Map<String,Object> getPointBy(int id){
        Map<String,Object> paramMap=new HashMap<>();
        TbClubIntegralRule tbClubIntegralRule = tbClubIntegralRuleMapper.selectByPrimaryKey(id);//积分规则
        logger.warn("------积分规则----------->>>>>"+ JSON.toJSONString(tbClubIntegralRule));
        String[] strGrade = tbClubIntegralRule.getFinishGrade().split("-");//评分
        List<Double> gradeList = new ArrayList<>();
        for (int i = 0; i < strGrade.length; i++) {
            gradeList.add(Double.valueOf(strGrade[i]));
        }
        paramMap.put("grade",gradeList);
        String[] strPoint = tbClubIntegralRule.getPoint().split("-");//对应的积分
        List<Double> pointList = new ArrayList<>();
        for (int i = 0; i < strPoint.length; i++) {
            pointList.add(Double.valueOf(strPoint[i]));
        }
        paramMap.put("point",pointList);
        paramMap.put("rate",tbClubIntegralRule.getRate());
        return paramMap;
    }


    /**
     * 获取俱乐部积分排名
     * @param reqClubListInfo
     * @return
     */
    @Override
    public APIResponse<Map<String,Object>> getClubIntegralRank(ReqClubListInfo reqClubListInfo) {
        Map<String,Object> paramMap=reqClubListInfo.getParamMap();
        if (!paramMap.containsKey("clubId") && !paramMap.containsKey("categoryId")){
            return APIResponse.returnFail(ApiResponseEnum.PARAMETER_CANT_BE_EMPTY);
        }
        Integer clubid= (Integer) paramMap.get("clubId");
        Integer clubType= (Integer) paramMap.get("categoryId");//俱乐部类别，足篮网羽
        Map<String,Object> param=new HashMap<>();
        param.put("pageNum",reqClubListInfo.getPageNum()*reqClubListInfo.getPageSize());
        param.put("pageSize",reqClubListInfo.getPageSize());
        param.put("clubType",clubType);
        if (paramMap.containsKey("cityId")){//全国榜
            Integer cityId= (Integer) paramMap.get("cityId");
            paramMap.clear();
            if(0==cityId){//全国榜
                List<RespClubIntegralRank> respClubIntegralRanks= clubIntegralMapper.getClubIntegral(param);//查询全国排名
                int countNum= clubIntegralMapper.getClubIntegralCountNum(param);
                PageObj<List<RespClubIntegralRank>> result=PageObj.create(countNum,reqClubListInfo.getPageNum(),reqClubListInfo.getPageSize(),respClubIntegralRanks);
                param.put("clubId",clubid);
                List<RespClubIntegralRank> respClubIntegralRankList= clubIntegralMapper.getClubIntegral(param);//查询该俱乐部排名
                paramMap.put("RankAll",result);//全国排名
                paramMap.put("RankSelf",respClubIntegralRankList.get(0));//该俱乐部排名
                return APIResponse.returnSuccess(paramMap);
            }else if (cityId>0){
                TbClub tbClub=tbClubMapper.selectByPrimaryKey(clubid);
                param.put("cityId",cityId);
                List<RespClubIntegralRank> respClubIntegralRanks= clubIntegralMapper.getClubIntegral(param);//查询该城市下俱乐部的排名
                int countNum= clubIntegralMapper.getClubIntegralCountNum(param);
                PageObj<List<RespClubIntegralRank>> result=PageObj.create(countNum,reqClubListInfo.getPageNum(),reqClubListInfo.getPageSize(),respClubIntegralRanks);
                paramMap.put("RankAll",result);//城市排名
                if(tbClub.getCityId().equals(cityId)){//判断该俱乐部是否在该城市
                    param.put("clubId",clubid);
                    List<RespClubIntegralRank> respClubIntegralRankList= clubIntegralMapper.getClubIntegral(param);//查询该俱乐部所在城市的该俱乐部排名
                    paramMap.put("RankSelf",respClubIntegralRankList.get(0));//该俱乐部排名
                }else{
                    RespClubIntegralRank respClubIntegralRank=new RespClubIntegralRank();
                    respClubIntegralRank.setClubIntegral(tbClub.getClubIntegr());
                    paramMap.put("RankSelf",respClubIntegralRank);//俱乐部积分
                }
                return APIResponse.returnSuccess(paramMap);
            }else{
                return APIResponse.returnFail("该城市不存在");
            }
        }
        return APIResponse.returnFail(ApiResponseEnum.PARAMETER_INVALID);
    }

    /**
     * 俱乐部首页获取俱乐部积分全国排名
     * @param clubId
     * @return
     */
    @Override
    public RespClubIntegralRank getClubIntegralRankByClubId(int clubId,int clubType) {
        Map<String,Object> param=new HashMap<>();
        param.put("clubId",clubId);
        param.put("clubType",clubType);
        List<RespClubIntegralRank> respClubIntegralRankList= clubIntegralMapper.getClubIntegral(param);//查询该俱乐部全国排名
        if (!CollectionUtils.isEmpty(respClubIntegralRankList)){
            TbClub tbClub=tbClubMapper.selectByPrimaryKey(clubId);
            RespClubIntegralRank respClubIntegralRank=respClubIntegralRankList.get(0);
            double clubStart=tbClub.getActivityCount()>0?tbClub.getStar()/Double.valueOf(tbClub.getActivityCount()):0.00;
            respClubIntegralRank.setClubStar(clubStart);
            return respClubIntegralRank;
        }
        return null;
    }

    /**
     * 俱乐部积分开关：0开，1关
     * @return
     */
    @Override
    public Byte getIntegralSwitch() {
        TbClubIntegralRule tbClubIntegralRule=tbClubIntegralRuleMapper.selectByPrimaryKey(5);
        return tbClubIntegralRule.getIsDelete();
    }

    /**
     * 跟新搜索后俱乐部星级
     * @param clubId
     * @return
     */
    @Override
    public double updateSearchClubStar(int clubId) {
        DecimalFormat df=new DecimalFormat("#.00");
        double newStar=0.00;
        TbClub tbClub=tbClubMapper.selectByPrimaryKey(clubId);
        if (tbClub.getActivityCount()!=0){
            newStar=tbClub.getStar()/tbClub.getActivityCount();
        }
        return Double.valueOf(df.format(newStar));
    }


    @Autowired
    private TbClubTaskSummaryLogMapper clubTaskSummaryLogMapper;
    @Autowired
    private TbClubTaskParameterMapper clubTaskParameterMapper;

    /**
     * 根据周任务的记录，重新计算俱乐部的周任务产生的积分
     */
    @Override
    public void reindexClubWeekTaskIntegral(){
        logger.warn("rdx wk igl: reindexClubWeekTaskIntegral 开始。");
        TbClubTaskSummaryLogExample example = new TbClubTaskSummaryLogExample();
        example.createCriteria()
                .andActivityCountGreaterThan(0).andSignupCountGreaterThan(0);
        int total = clubTaskSummaryLogMapper.countByExample(example);
        int pageSize = 500;
        int pageCount = total/pageSize;
        pageCount += (total%pageSize)==0?0:1;
        logger.warn("rdx wk igl: 周任务记录总共"+total+"条，分"+pageCount+"页，每页"+pageSize+"条");

        for (int i = 1; i <= pageCount; i++) {
            example.setLimit(Limit.buildLimit(i, pageSize));
            List<TbClubTaskSummaryLog> summaryLogs = clubTaskSummaryLogMapper.selectByExample(example);
            if (summaryLogs == null || summaryLogs.size() == 0){
                continue;
            }
            logger.warn("rdx wk igl: 第" + i + "页，开始计算：");
            long t = System.currentTimeMillis();
            for (TbClubTaskSummaryLog log : summaryLogs){
                int taskId = log.getTaskParameterId();
                TbClubTaskParameter parameter = clubTaskParameterMapper.selectByPrimaryKey(taskId);
                if (parameter == null){
                    continue;
                }
                int targetActivityCount = parameter.getActivityTargetCount();
                int targetSignupCount = parameter.getSignupTargetCount();

                this.modifyClubWeekTaskStar(log.getClubId(), log.getActivityCount(), targetActivityCount,
                        log.getSignupCount(), targetSignupCount);
                this.calcClubActivityMember(log.getClubId(), log.getSignupPerson());
            }
            logger.warn("rdx wk igl: 第" + i + "页，结束计算，花费：" + (System.currentTimeMillis()-t) + "ms");
        }
        logger.warn("rdx wk igl: reindexClubWeekTaskIntegral 结束。");
    }
}
